import { Dishes } from "@prisma/client";
import prisma from "../config/database";
import {
  CreateDishesRequestDTO,
  UpdateDishesRequestDTO,
} from "../validators/dishes.validator";
import { DishResponseDTO } from "../dtos/dishes.dto";
import { getNextMonday } from "../utils/date.util";

export class DishService {
  /**
   * 根据ID获取菜品详情
   */
  public static async getDishById(id: number): Promise<DishResponseDTO | null> {
    const dishes = await prisma.dishes.findUnique({
      where: { id },
      include: { category: true },
    });

    if (!dishes) return null;

    const { category, ...rest } = dishes;
    return {
      ...rest,
      categoryName: category.name,
      description: rest.description || "",
      picture: rest.picture || "",
      thumbnail: rest.thumbnail || "",
    };
  }

  /**
   * 创建新菜品
   * @param data 菜品数据
   * @returns 创建的菜品信息
   */
  public static async createDish(
    data: CreateDishesRequestDTO
  ): Promise<Dishes> {
    try {
      // 验证分类是否存在
      const category = await prisma.category.findUnique({
        where: { id: data.categoryId },
      });

      if (!category) {
        throw new Error(`分类ID ${data.categoryId} 不存在`);
      }

      // 创建菜品
      const dishes = await prisma.dishes.create({
        data: {
          categoryId: data.categoryId,
          name: data.name,
          description: data.description,
          picture: data.picture,
          thumbnail: data.thumbnail,
          avgRating: 0,
          ratingCount: 0,
          totalScore: 0,
        },
      });

      return dishes;
    } catch (error) {
      console.error("创建菜品失败:", error);
      throw new Error(error instanceof Error ? error.message : "创建菜品失败");
    }
  }

  /**
   * 获取所有菜品
   */
  public static async listAll(): Promise<DishResponseDTO[]> {
    const dishList = await prisma.dishes.findMany({
      orderBy: { createdAt: "desc" },
      include: {
        category: true,
      },
    });

    // dishes 转换成 DishesResponseDTO
    const list = dishList.map((item) => {
      const { category, ...dishes } = item;
      return {
        ...dishes,
        categoryName: category.name,
        description: dishes.description || "",
        picture: dishes.picture || "",
        thumbnail: dishes.thumbnail || "",
      };
    });

    return list;
  }

  // 查询所有菜品，菜品中包含isWished字段，值为true表示用户下周想吃
  public static async listAllWithIsWished(userId: number) {
    const nextMonday = getNextMonday();
    const list = await prisma.dishes.findMany({
      orderBy: { createdAt: "desc" },
      include: {
        category: true,
        wishes: {
          where: {
            userId,
            date: new Date(nextMonday),
          },
        },
      },
    });

    // dishes 转换成 DishesResponseDTO
    const dishesList = list.map((item) => {
      const { category, wishes, ...dishes } = item;
      return {
        ...dishes,
        categoryName: category.name,
        description: dishes.description || "",
        picture: dishes.picture || "",
        thumbnail: dishes.thumbnail || "",
        isWished: wishes.length > 0,
      };
    });

    return dishesList;
  }

  // 根据菜品分类id查询菜品
  public static async getDishesByCategoryId(
    categoryId: number
  ): Promise<DishResponseDTO[]> {
    const dishList = await prisma.dishes.findMany({
      where: {
        categoryId,
      },
      orderBy: { createdAt: "desc" },
      include: {
        category: true,
      },
    });

    // dishes 转换成 DishesResponseDTO
    const list = dishList.map((item) => {
      const { category, ...dishes } = item;
      return {
        ...dishes,
        categoryName: category.name,
        description: dishes.description || "",
        picture: dishes.picture || "",
        thumbnail: dishes.thumbnail || "",
      };
    });

    return list;
  }

  /**
   * 根据菜品分类id查询菜品，
   * 菜品中包含isWished字段，值为true表示用户下周想吃
   */
  public static async getDishesWithIsWishedByCategoryId(
    categoryId: number,
    userId: number
  ) {
    const nextMonday = getNextMonday();
    const dishList = await prisma.dishes.findMany({
      where: {
        categoryId,
      },
      orderBy: { createdAt: "desc" },
      include: {
        category: true,
        wishes: {
          where: {
            userId,
            date: new Date(nextMonday),
          },
        },
      },
    });

    // dishes 转换成 DishesResponseDTO
    const list = dishList.map((item) => {
      console.log(item);
      const { category, wishes, ...dishes } = item;
      return {
        ...dishes,
        categoryName: category.name,
        description: dishes.description || "",
        picture: dishes.picture || "",
        thumbnail: dishes.thumbnail || "",
        isWished: wishes.length > 0,
      };
    });

    return list;
  }

  /**
   * 更新菜品
   */
  public static async updateDish(
    id: number,
    data: UpdateDishesRequestDTO
  ): Promise<Dishes | null> {
    try {
      const updatedDish = await prisma.dishes.update({
        where: { id },
        data,
      });

      if (!updatedDish) return null;
      return updatedDish;
    } catch (error) {
      console.error("更新菜品失败:", error);
      throw new Error(error instanceof Error ? error.message : "更新菜品失败");
    }
  }

  /**
   * 删除菜品
   */
  public static async deleteDish(id: number) {
    try {
      await prisma.dishes.deleteMany({
        where: { id },
      });
    } catch (error) {
      console.error("删除菜品失败:", error);
      throw new Error(error instanceof Error ? error.message : "删除菜品失败");
    }
  }

  /**
   * 菜品评分
   */
  public static async rateDish(id: number, score: number, userId: number) {
    try {
      // 今日菜单中是否存在该菜品
      const todayMenu = await prisma.menu.findFirst({
        where: {
          date: new Date(),
        },
        include: {
          menuDishes: true,
        },
      });

      if (!todayMenu) {
        throw new Error(`今日菜单不存在`);
      }

      const menuDish = todayMenu.menuDishes.find(
        (item) => item.dishesId === id
      );
      if (!menuDish) {
        throw new Error(`今日菜单中不存在菜品ID ${id}`);
      }

      const dish = await prisma.dishes.findUnique({
        where: { id },
      });

      if (!dish) {
        throw new Error(`菜品ID ${id} 不存在`);
      }

      // 创建一个评分
      const existingRating = await prisma.rating.findFirst({
        where: {
          userId,
          dishesId: id,
          menuId: todayMenu.id,
        },
      });
      if (existingRating) {
        throw new Error(`用户ID ${userId} 已对菜品ID ${id} 进行评分`);
      }
      await prisma.rating.create({
        data: {
          userId,
          dishesId: id,
          menuId: todayMenu.id,
          score,
        },
      });

      // 计算新的平均评分
      const newTotalScore = dish.totalScore + score;
      const newRatingCount = dish.ratingCount + 1;
      let newAvgRating =
        newRatingCount > 0 ? newTotalScore / newRatingCount : 0;
      newAvgRating = Number(newAvgRating.toFixed(1));

      await prisma.dishes.update({
        where: { id },
        data: {
          totalScore: newTotalScore,
          ratingCount: newRatingCount,
          avgRating: newAvgRating,
        },
      });
    } catch (error) {
      console.error("评分失败:", error);
      throw new Error(error instanceof Error ? error.message : "评分失败");
    }
  }
}
